//
//  NSString+AES128.m
//  todoApp
//
//  Created by wangyaqing on 15/2/26.
//  Copyright (c) 2015年 ll studio. All rights reserved.
//

#import "NSString+AES128.h"
#import "NSData+base64.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSString (AES128)

- (NSString *)AES128EncryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
    
    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    // pad key with n. Private rule, agree with server, add by lipeng
    unsigned long keylen = strlen(keyPtr);
    for (long i = keylen; i < kCCKeySizeAES128; ++i) {
        keyPtr[i] = (kCCKeySizeAES128 - keylen);
    }
    
    NSData *dataText = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [dataText length];
    
    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCKeySizeAES128,
                                          NULL /* initialization vector (optional) */,
                                          [dataText bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        NSData *result = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        //        NSLog(@"%s in hex.. %@", __FUNCTION__, [result description]);
        NSString *strResult = [result base64EncodedString];
        return strResult;
    }
    free(buffer);
    return @"";
}

- (NSString *)AES128DecryptWithKey:(NSString *)key {
    char keyPtr[kCCKeySizeAES128+1];
    bzero(keyPtr, sizeof(keyPtr));
    
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    // pad key with n  agree with server, add by lipeng
    unsigned long keylen = strlen(keyPtr);
    for (long i = keylen; i < kCCKeySizeAES128; ++i) {
        keyPtr[i] = (kCCKeySizeAES128 - keylen);
    }
    
    NSData *dataText = [NSData dataFromBase64String:self];
    NSUInteger dataLength = [dataText length];
    
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [dataText bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    
    if (cryptStatus == kCCSuccess) {
        NSData *result = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        //NSLog(@"%s in hex.. %@", __FUNCTION__, [result description]);
        //NSString *strResult = [result base64EncodedString];
        NSString* strResult = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
        return strResult;
    }
    free(buffer);
    return nil;
}

@end
